# -*- coding: UTF-8 -*-
# 2023/11/29 21:17
"""
下载分类预览图
"""
import os.path
from concurrent.futures import ThreadPoolExecutor

import _tkinter
import requests
from retry import retry

from tools.get_configer import my_configer
from tools.get_logger import get_logger
from tools.img_tool import set_pil_img

configer = my_configer()
loger = get_logger()


class pool_download_preview_img:
    """
    在线程池进行独立下载分类封面,并after回调更新封面
    传入的btn_list 确保btn包含以下属性
    img_name_id_urls = [
        {"img_name": f'{"_".join(img_info["tag"])}_{img_info["id"]}.jpg',
         "img_id": img_info["id"],
         "img_url":
             {
                 "thumb": img_info["thumb"],  # 预览350*540
                 "img": img_info["img"],  # 标准大小1080*1920
                 "preview": img_info["preview"]  # 最大2000*300,存在损坏的
             }
         } for img_info in response["res"]["vertical"]
    ]

    btn_img_id = getattr(btn, "btn_img_id")
    btn_img_url = getattr(btn, "btn_img_url")
    btn_name = getattr(btn, "btn_name")
    btn_cover_save_path = getattr(btn, "btn_cover_save_path")
    """

    def __init__(self, button_list: list):
        """
        批量下载任务
        :param button_list: 待下载图片列表
        """
        self.button_list = button_list  # btn可获取信息:btn_img_id/btn_img_url/btn_img_save_path

        self.run()

    def run(self):
        with ThreadPoolExecutor(max_workers=8) as download_pool:  # 创建一个最大容纳数量为max_workers的线程池
            for check_button in self.button_list:
                btn_img_name_id_urls = getattr(check_button, "img_name_id_urls")
                save_path = os.path.abspath(f"./cache/phone_cache/{btn_img_name_id_urls['img_name']}")
                url = btn_img_name_id_urls["img_urls"]["thumb"]  # 预览350*540

                setattr(check_button, "save_path", save_path)
                setattr(check_button, "url", url)

                if not os.path.isfile(save_path):
                    task_future = download_pool.submit(self.download_img, url, save_path)
                    setattr(task_future, "check_button", check_button)
                    setattr(task_future, "save_path", save_path)
                    setattr(task_future, "url", url)

                    loger.info(f"提交下载多选按钮封面任务, 保存位置:{save_path}, 封面:{url}")

                    # 给所有task_future添加完成回调任务
                    task_future.add_done_callback(self.future_call_back)

                else:
                    loger.info(f"已下载多选按钮封面,直接更新,save_path:{save_path}, img_url:{url}")
                    check_button.after_idle(self.update_btn_img, check_button)

            download_pool.shutdown()

    def future_call_back(self, task_future):
        check_button = getattr(task_future, "check_button")
        save_path = getattr(task_future, "save_path")
        url = getattr(task_future, "url")

        task_future_result = task_future.result()
        try:
            # 如果返回None表示下载成功,更新对应按钮图片
            if task_future_result is None:
                check_button.after_idle(self.update_btn_img, check_button)
                loger.info(f"线程回调更新预览封面,save_path:{save_path}, img_url:{url}")

        except:
            task_future_exception = task_future.exception()
            loger.error(f"经过多次尝试,下载预览封面仍有future下载错误,报错信息为:{type(task_future_exception)}")

    def update_btn_img(self, check_button):
        try:
            button_img_save_path = getattr(check_button, "save_path")

            button_pil_image = set_pil_img(button_img_save_path, size=(210, 324))  # 此处由于只给分类用所以固定，根据需要可调整

            check_button.config(image=button_pil_image, compound='bottom')
            check_button.image = button_pil_image
            check_button.update()

        except _tkinter.TclError:
            loger.warning(f"更新多选按钮封面过程中遇到错误,可能所在窗口已关闭忽略!!")

    @retry(tries=5)
    def download_img(self, url: str, save_path: str) -> None:
        """
        根据传入的图片地址,进行下载
        :param self:
        :param url: 图片url
        :param save_path: 保存路径
        :return:
        """

        r = requests.get(url)
        response = r.content

        with open(save_path, "wb") as f:
            f.write(response)

        r.close()

        loger.info(f"图片保存成功,保存位置:{save_path},图片url:{url}")
